package com.example.easycharge.controller;

import com.example.easycharge.error.AttributeNotFoundError;
import com.example.easycharge.error.QueueNotFoundError;
import com.example.easycharge.notRepEntity.QueueOverview;
import com.example.easycharge.notRepEntity.WaitQueue;
import com.example.easycharge.repository.ChargePileRepository;
import com.example.easycharge.repository.VehicleRepository;
import com.example.easycharge.service.ChargeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

@Tag(name = "队列接口组")
@RestController
@RequestMapping("queue")
public class QueueController {

    @Autowired
    private ChargeService chargeService;

    @Operation(description = "获取到所有的充电队列")
    @GetMapping("waitMonitor")
    public Collection<WaitQueue> getAllWaitQueue() {
        return chargeService.getAllWaitQueue();
    }

    @Operation
    @GetMapping("admin/overview")
    public QueueOverview getQueueOverview() {
        double queueAvgNum = 0;
        int queueMaxNum = 0;
        int queueMinNum = Integer.MAX_VALUE;
        int queueAvgTime = 0;
        int queueMaxTime = 0;
        int queueMinTime = Integer.MAX_VALUE;
        int totalNum = 0;
        int totalTime = 0;
        Collection<WaitQueue> queueList = chargeService.getAllWaitQueue();
        for (WaitQueue queue : queueList) {
            totalNum += queue.getWaitLength();
            totalTime += queue.getTotalWaitTime();
            if (queue.getWaitLength() > queueMaxNum) {
                queueMaxNum = queue.getWaitLength();
            }
            if (queue.getWaitLength() < queueMinNum) {
                queueMinNum = queue.getWaitLength();
            }
            if (queue.getTotalWaitTime() > queueMaxTime) {
                queueMaxTime = queue.getTotalWaitTime();
            }
            if (queue.getTotalWaitTime() < queueMinTime) {
                queueMinTime = queue.getTotalWaitTime();
            }
        }
        queueAvgNum = (double) totalNum / queueList.size();
        queueAvgTime = totalTime / queueList.size();
        return new QueueOverview(queueAvgNum, queueMaxNum, queueMinNum, queueAvgTime, queueMaxTime, queueMinTime);
    }

    @Operation(description = "获取某个队列的详细信息，可以看到队列中等待的车辆的信息，明显是一个管理员接口")
    @GetMapping("admin/{pileId}")
    public WaitQueue getQueueById(@PathVariable("pileId") long pileId) throws QueueNotFoundError {
        HashMap<Long, WaitQueue> waitQueueMap = chargeService.getWaitQueue();
        long queueId = chargeService.getQueueId(pileId);
        if (waitQueueMap.containsKey(queueId)) {
            return waitQueueMap.get(queueId);
        } else {
            throw new QueueNotFoundError();
        }
    }


    @Operation(description = "获取的是等待队列，即保存在内存里的队列")
    @GetMapping("wait/{orderBy}/{page}/{pageNum}/{asc}")
    public Page<WaitQueue> getQueueDetail(@PathVariable("orderBy") String orderBy,
                                          @PathVariable("page") int page,
                                          @PathVariable("pageNum") int pageNum,
                                          @PathVariable("asc") boolean asc) throws AttributeNotFoundError {
        HashMap<Long, WaitQueue> waitQueueMap = chargeService.getWaitQueue();
        List<WaitQueue> waitQueueList = new ArrayList<>(waitQueueMap.values());
        AtomicBoolean noAtt = new AtomicBoolean(false);
        // 这里手动对List做排序,手动排序
        waitQueueList.sort((o1, o2) -> {
            int ori = 0;
            switch (orderBy) {
                case "chargePower":
                    ori = o1.getChargePower() - o2.getChargePower();
                    break;
                case "state":
                    ori = o1.getState().getIndex() - o2.getState().getIndex();
                    break;
                case "waitMinutes":
                    ori = o1.getWaitMinutes() - o2.getWaitMinutes();
                    break;
                case "leftMinutes":
                    ori = o1.getLeftMinutes() - o2.getLeftMinutes();
                    break;
                case "waitLength":
                    ori = o1.getWaitLength() - o2.getWaitLength();
                    break;
                case "totalWaitTime":
                    ori = o1.getTotalWaitTime() - o2.getTotalWaitTime();
                    break;
                default:
                    // 报错
                    noAtt.set(true);
            }
            if (asc) {
                return ori;
            }
            return -ori;
        });
        if (noAtt.get()) {
            throw new AttributeNotFoundError();
        }
        Pageable pageable = PageRequest.of(page - 1, pageNum);
        int start = (int) pageable.getOffset();
        int end = Math.min((start + pageable.getPageSize()), waitQueueList.size());
        return new PageImpl<>(waitQueueList.subList(start, end), pageable, waitQueueList.size());
    }
}
